﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Xml;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Threading;

namespace AutoUpdater
{
    public class UpdateHelper
    {
        private readonly string serviceUrl;

        public UpdateHelper(string serviceUrl)
        {
            this.serviceUrl = serviceUrl;
        }

        public string ServiceUrl
        {
            get { return serviceUrl; }
        }

        public UpdateInfo[] GetAllUpdateInfos()
        {
            using (Stream stream = new WebClient().OpenRead(ServiceUrl))
            {
                XmlReader reader = XmlReader.Create(stream);
                return (UpdateInfo[])new XmlSerializer(typeof(UpdateInfo[])).Deserialize(reader);
            }
        }

        public UpdateInfo[] NeedUpdateInfos()
        {
            return Array.FindAll(GetAllUpdateInfos(), CheckIfNeedUpdate);
        }

        public bool CheckAllIfNeedUpdate()
        {
            return Array.Exists(GetAllUpdateInfos(), CheckIfNeedUpdate);
        }

        public void UpdateAllFiles()
        {
            List<Thread> downloadsThreads = new List<Thread>();
            foreach (UpdateInfo update in NeedUpdateInfos())
            {
                Thread thread = new Thread(delegate(object param) { DownloadFile((string)param); });
                thread.Start(update.FileName);
                downloadsThreads.Add(thread);
            }
            foreach (Thread thread in downloadsThreads) thread.Join();
        }

        public bool CheckIfNeedUpdate(UpdateInfo update)
        {
            if (!File.Exists(update.FileName))
            {
                return true;
            }
            else
            {
                switch (update.VersionType)
                {
                    case VersionType.FileVersion:
                        return FileVersionInfo.GetVersionInfo(update.FileName).FileVersion != update.Version;
                    case VersionType.MD5:
                        using (FileStream file = File.OpenRead(update.FileName))
                        {
                            return Convert.ToBase64String(MD5.Create().ComputeHash(file)) != update.Version;
                        }
                    default: return false;
                }
            }
        }

        public void DownloadFile(string fileName)
        {
            new WebClient().DownloadFile(ServiceUrl + "?download=" + fileName, fileName);
        }
    }
}